/*****************************************************************************
 * file  : os obj .c
 * creat : apleilx
 * data  : 2017/03/02
 *******************************************************************************/
#define __os_obj_creat__ // define objects in rtxapp module
#include "os_obj.h"		 // RTOS object definitions
#include "common.h"
#include "bsp_api.h"

void task_system(void const *argument);
void modbus_task(void const *argument);
void usb_task(void const *argument);
void task_console(void const *argument);

// 独立堆栈 需定义
osThreadDef(thd_sys, task_system, osPriorityHigh, 0, 0x1000);
osThreadDef(thd_usb, usb_task, osPriorityLow, 0, 0x1000);
osThreadDef(thd_con, task_console, osPriorityNormal, 0, 0x4000);

/*******************************************************************************
 * @brief: thread obj init
 * @param {*}
 * @return {*}
 ******************************************************************************/
int thread_init(void)
{
	/* creat mutex */
	tx_mutex_create(&os_obj.mutex_printf,
					"mutex_printf",
					TX_NO_INHERIT); // no prio
	os_obj.mid_printf = &os_obj.mutex_printf;

	tx_mutex_create(&os_obj.mutex_malloc,
					"mutex_malloc",
					TX_NO_INHERIT); // no prio
	os_obj.mid_malloc = &os_obj.mutex_malloc;

	tx_mutex_create(&os_obj.mutex_file,
					"mutex_file",
					TX_NO_INHERIT); // no prio
	os_obj.mid_file = &os_obj.mutex_file;

	tx_semaphore_create(
		&os_obj.sem_mb,
		"sem_mb",
		1);
	os_obj.sid_mb = &os_obj.sem_mb;

	// 系统对象创建
	os_obj.tid_sys_task = osThreadCreate(osThread(thd_sys), NULL);

	return (0);
}

/*******************************************************************************
 * @brief: thread creat
 * @param {*}
 * @return {*}
 ******************************************************************************/
int thread_create(void)
{
	// 任务创建
	os_obj.tid_console_task = osThreadCreate(osThread(thd_con), NULL);
	os_obj.tid_usb_task = osThreadCreate(osThread(thd_usb), NULL);

	return (0);
}

/*******************************************************************************
 * @brief: os lock
 * @param {*}
 * @return {*}
 ******************************************************************************/
void os_lock(void)
{
}

void os_unlock(void)
{
}

/*******************************************************************************
 * @brief: stack used
 * @param tid
 * @return {*}
 ******************************************************************************/
int32_t os_task_stk_used(osThreadId tid)
{
	uint32_t start, end, unused;

	start = (uint32_t)tid->tx_thread_stack_start;
	end = (uint32_t)tid->tx_thread_stack_end;

	unused = start;

	while (inpw(unused) == 0xEFEFEFEF && inpw(unused + 4) == 0xEFEFEFEF)
	{
		unused += 8;
	}

	return ((end + 1) - unused);
}

/*******************************************************************************
 * @brief: task info
 * @param {*}
 * @return {*}
 ******************************************************************************/
int task_info(int argc, char *argv[])
{
	extern TX_THREAD *_tx_thread_created_ptr;
	TX_THREAD *tid = _tx_thread_created_ptr;

	dbg_print(SYMBOL_LINE_EQ CR);
	
	do
	{
		int32_t stk_used = os_task_stk_used(tid);

		dbg_print("prio: %-3d, run count: %-8d :: stack (%08x - %08x), "
				  "size %5d, used %5d # %-3d%% :: %s\n",
				  tid->tx_thread_priority,
				  tid->tx_thread_run_count,
				  tid->tx_thread_stack_start,
				  tid->tx_thread_stack_end,
				  tid->tx_thread_stack_size,
				  stk_used,
				  stk_used * 100 / tid->tx_thread_stack_size,
				  tid->tx_thread_name);

		tid = tid->tx_thread_created_next;
	} while (tid && tid != _tx_thread_created_ptr);

	return 0;
}
SHELL_FUN_EXPORT(task_info);